package cz.muni.fi.pa165.carpark.dao;

import cz.muni.fi.pa165.carpark.EmployeePosition;
import cz.muni.fi.pa165.carpark.VehicleStatus;
import cz.muni.fi.pa165.carpark.entities.ServiceCheck;
import cz.muni.fi.pa165.carpark.entities.Vehicle;
import java.util.Collections;
import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import org.springframework.stereotype.Repository;

/**
 *
 * @author xmarton1
 */
@Repository
public class VehicleDAOImpl implements VehicleDAO {

    @PersistenceContext
    private EntityManager em;

    @Override
    public void create(Vehicle vehicle) {
        if (vehicle == null || vehicle.getId() != null) {
            throw new IllegalArgumentException("Illegal entity in create function");
        } else {
            em.persist(vehicle);
        }
    }
    
    @Override
    public Vehicle get(Long id){
        if(id == null || id < 0) {
            throw new IllegalArgumentException();
        }
        Vehicle vehicle = em.find(Vehicle.class, id);
        return vehicle;
    }

    @Override
    public void update(Vehicle vehicle) {
        if(vehicle == null || vehicle.getId() == null || vehicle.getId() < 0) {
            throw new IllegalArgumentException();
        }
        
        boolean hasActive = false;
        for(ServiceCheck s : vehicle.getControlServiceCheck()){
             if((!s.isCheckDone()) && (s.getLastCheck() + s.getCheckInterval()) < vehicle.getNumberOfKms()){
                s.setIsActive(true);
                hasActive = true;
             }
        }
        if(hasActive){
            vehicle.setStatus(VehicleStatus.MAINTENANCE_REQUIRED);
        }
        em.merge(vehicle);
    }

    @Override
    public void remove(Vehicle vehicle) {
        if(vehicle == null || vehicle.getId() == null || vehicle.getId() < 0) {
            throw new IllegalArgumentException();
        }
        Vehicle v = em.find(Vehicle.class, vehicle.getId());
        em.remove(v);
    }

    @Override
    public List<ServiceCheck> getActiveServiceChecks(Vehicle vehicle,boolean active){
         if(vehicle == null || vehicle.getId() == null){
            throw new IllegalArgumentException();
         }
         
        TypedQuery<ServiceCheck> query = em.createQuery("SELECT s FROM Vehicle v,IN(v.controlServiceCheck) s "
                + "WHERE v = :vehicle AND s.isActive = :active", ServiceCheck.class);
        query.setParameter("active", active);
        query.setParameter("vehicle", vehicle);
        List<ServiceCheck> serviceList = query.getResultList();
        return Collections.unmodifiableList(serviceList);
    }

    @Override
    public List<Vehicle> findAllVehiclesForPosition(EmployeePosition position) {
        TypedQuery<Vehicle> query = em.createQuery("SELECT v FROM Vehicle v WHERE v.status = :status AND v.availableForPositions >= :position", Vehicle.class);
        query.setParameter("position", position);
        query.setParameter("status", VehicleStatus.AVAILABLE);
        List<Vehicle> vehicleList = query.getResultList();
        return Collections.unmodifiableList(vehicleList);
    }

    @Override
    public List<Vehicle> findAllVehicles() {
        TypedQuery<Vehicle> query = em.createQuery("SELECT v FROM Vehicle v", Vehicle.class);
        List<Vehicle> vehicleList = query.getResultList();
        return Collections.unmodifiableList(vehicleList);
    }
    
    @Override
    public List<Vehicle> getVehiclesByStatus(VehicleStatus status){
        TypedQuery<Vehicle> query = em.createQuery("SELECT v FROM Vehicle v WHERE v.status = :status", Vehicle.class);
        query.setParameter("status", status);
        List<Vehicle> vehicleList = query.getResultList();
        return Collections.unmodifiableList(vehicleList);
    }

    public void setEm(EntityManager em) {
        this.em = em;
    }

}
